<?php
declare(strict_types=1);

namespace Lshorz\LaravelConfig;

use ArrayAccess;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Cache;

abstract class CfgHandlerAbstract implements ArrayAccess
{
    /**
     * All of the configuration items.
     *
     * @var array
     */
    protected array $items = [];

    /**
     * 配置缓存KEY
     * @var string
     */
    private string $cfgCacheKey = '';

    /**
     * 配置标识：文件名或id
     * @var mixed
     */
    private string $identifier;

    /**
     * 设置标识:[文件名|配置名|keys]
     *
     * @param string $ident
     * @param string $driverName
     * @return void
     */
    protected function setIdentifier(string $ident, string $driverName): void
    {
        $this->identifier = $ident;

        //设置cacheKey
        if (config('cfg.cache.open')) {
            $this->cfgCacheKey = config('cfg.cache.key_prefix') . $driverName . ":" . $ident;
        }
    }

    /**
     * 返回配置标识
     *
     * @return string
     */
    public function getIdentifier(): string
    {
        return $this->identifier;
    }

    /**
     * 检查配置中是否存在键值为$key的值
     *
     * @param string $key
     * @return bool
     */
    public function has(string $key): bool
    {
        return Arr::has($this->items, $key);
    }

    /**
     * 根据键值获取配置
     *
     * @param array|string|null $key
     * @param mixed $default
     * @return mixed
     */
    public function get($key = null, $default = null)
    {
        if (is_array($key)) {
            return $this->getMany($this->items, $key);
        }

        return Arr::get($this->items, $key, $default);
    }

    /**
     * 获取整个配置数组
     *
     * @return array
     */
    public function all(): array
    {
        return $this->items;
    }

    /**
     * 设置配置值
     *
     * @param  array|string  $key
     * @param  mixed  $value
     * @return self
     */
    public function set($key, $value = null): self
    {
        $keys = is_array($key) ? $key : [$key => $value];

        foreach ($keys as $key => $value) {
            Arr::set($this->items, $key, $value);
        }
        return $this;
    }

    /**
     * 将值插入到数组配置值前面
     *
     * @param  string  $key
     * @param  mixed  $value
     * @return self
     */
    public function prepend(string $key, $value): self
    {
        $array = $this->get($key, []);

        array_unshift($array, $value);

        $this->set($key, $array);

        return $this;
    }

    /**
     * 值插入到数组配置值后面
     *
     * @param  string  $key
     * @param  mixed  $value
     * @return self
     */
    public function push(string $key, $value): self
    {
        $array = $this->get($key, []);

        $array[] = $value;

        $this->set($key, $array);

        return $this;
    }

    /**
     * Determine if the given configuration option exists.
     *
     * @param  string  $key
     * @return bool
     */
    #[\ReturnTypeWillChange]
    public function offsetExists($key)
    {
        return $this->has($key);
    }

    /**
     * Get a configuration option.
     *
     * @param  string  $key
     * @return mixed
     */
    #[\ReturnTypeWillChange]
    public function offsetGet($key)
    {
        return $this->get($key);
    }

    /**
     * Set a configuration option.
     *
     * @param  string  $key
     * @param  mixed  $value
     * @return void
     */
    #[\ReturnTypeWillChange]
    public function offsetSet($key, $value)
    {
        $this->set($key, $value);
    }

    /**
     * Unset a configuration option.
     *
     * @param  string  $key
     * @return void
     */
    #[\ReturnTypeWillChange]
    public function offsetUnset($key)
    {
        $this->set($key, null);
    }

    /**
     * 获取多个配置值
     *
     * @param array $items
     * @param array $keys
     * @return array
     */
    protected function getMany(array $items, array $keys): array
    {
        $config = [];

        foreach ($keys as $key => $default) {
            if (is_numeric($key)) {
                [$key, $default] = [$default, null];
            }

            $config[$key] = Arr::get($items, $key, $default);
        }

        return $config;
    }

    /**
     * 创建缓存
     *
     * @param array $items
     * @return bool
     */
    protected function cacheCreate(array $items): bool
    {
        if (config('cfg.cache.open') == false || empty($items)) {
            return false;
        }

        $ttl = config('cfg.cache.ttl');
        if ($ttl == -1) {
            return Cache::forever($this->cfgCacheKey, $items);
        } else {
            return Cache::put($this->cfgCacheKey, $items, $ttl);
        }
    }

    /**
     * 删除缓存
     *
     * @return bool
     */
    protected function cacheDestroy(): bool
    {
        if (config('cfg.cache.open') == false) {
            return false;
        }

        return Cache::forget($this->cfgCacheKey);
    }

    /**
     * 获取缓存
     *
     * @return mixed
     */
    protected function cacheGet()
    {
        if (config('cfg.cache.open') == false) {
            return false;
        }

        return Cache::get($this->cfgCacheKey);
    }
}
